/*
 * @Author: AiLjx
 * @Date: 2023-03-02 20:19:46
 * @LastEditors: AiLjx
 * @LastEditTime: 2023-03-02 22:13:20
 */
// 这里实现的Watcher与Vue2中基本的watch一样，只能侦听到一层数据
export default class Watcher {
  //vm:监听对象；expOrFn:监听的表达式或函数,如a.m；cb:回调函数；
  constructor(vm, expOrFn, cb) {
    this.vm = vm;
    //执行this.getter()，就可以读取a.m的内容
    this.getter = parsePath(expOrFn);
    this.cb = cb;
    this.value = this.get();
  }
  get() {
    //进入依赖收集阶段
    window.target = this;
    // call(上下文，参数1,参数2,..),这里值将this.getter方法放到this.vm里执行，后面的this.vm是传入this.getter方法的参数

    //这里执行this.getter()函数的时候获取了响应式数据的值，触发了响应式数据的getter，即defineReactive中defineProperty的get
    //则defineProperty的get就可以通过window.target收集这个依赖
    const data = this.vm;
    const value = this.getter.call(data, data);
    window.target = undefined;
    return value;
  }
  update() {
    // 重新执行get方法
    const value = this.get();
    // 渲染watcher的value是undefined，因为渲染函数没有返回值
    // 因此value和this.value都是undefined，不会进入if
    // 如果依赖是对象，要触发更新
    if (value !== this.value || (typeof value === "object" && value !== null)) {
      const oldValue = this.value;
      this.value = value;
      this.cb.call(this.vm, value, oldValue);
    }
    // const oldValue = this.value;
    // this.value = this.get();
    // this.cb.call(this.vm, this.value, oldValue);
  }
}

function parsePath(str) {
  const segments = str.split(".");
  return (obj) => {
    for (let i = 0; i < segments.length; i++) {
      if (!obj) return;
      obj = obj[segments[i]];
    }
    return obj;
  };
}
